package org.apache.hdfs;

import java.io.*;
import java.nio.charset.CharsetEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * 用来读取MR运算结果的part-r文件，可以指定某一个文件，也可以是一个输出文件夹，支持多个Reducer的输出读取方式。
 * 如果存在多个part-r文件，会自动合并所有文件的内容。<br>
 * 输出格式为：Key-Value格式，Key是行号，value是当前行的数组
 */
public class FileUtil {

    /**
     * 将MR结果的输出文件夹中所有的part-r文件中的内容自动读取<br>
     * <blockquote><pre>
     *     Map<Integer,String[]> items = FileUtil.ReadAllPartFiles("output");
     *         for(Integer key :items.keySet()){
     *             System.out.print(key+"=");
     *             String[] value= items.get(key);
     *             System.out.println(value[0]+","+value[1]);
     *         }</blockquote></pre>
     *
     * @param path MR的输出目录
     * @return 输出格式为：Key-Value格式，Key是行号，value是当前行的数组
     * @throws IOException
     */
    public static Map<Integer, String[]> ReadAllPartFiles(String path) throws IOException {

        return  ReadAllPartFiles(path,"utf-8");
    }
    /**
     * 将MR结果的输出文件夹中所有的part-r文件中的内容自动读取<br>
     * <blockquote><pre>
     *     Map<Integer,String[]> items = FileUtil.ReadAllPartFiles("output","utf-8"));
     *         for(Integer key :items.keySet()){
     *             System.out.print(key+"=");
     *             String[] value= items.get(key);
     *             System.out.println(value[0]+","+value[1]);
     *         }</blockquote></pre>
     *
     * @param path MR的输出目录
     * @param charset 当前文件的字符集编码（注意：MR的输入/出默认是UTF8编码）
     * @return 输出格式为：Key-Value格式，Key是行号，value是当前行的数组
     * @throws IOException
     */
    public static Map<Integer, String[]> ReadAllPartFiles(String path,String charset) throws IOException {
        File file = new File(path);
        Map<Integer, String[]> items = new HashMap<>();
        if (!file.exists()) {
            throw new FileNotFoundException(path + "文件夹不存在！");
        }
        File[] files = file.listFiles();
        for (File f : files) {
            if (f.getName().startsWith("part-r-000")) {
                Map<Integer, String[]> tmpMap = ReadPartFile(f.getPath(),charset);
                int startIndex = items.size();
                for (Integer tmp : tmpMap.keySet()) {
                    items.put(startIndex++, tmpMap.get(tmp));
                }
            }
        }
        return items;
    }
    /**
     * 将MR结果的输出文件夹中所有的part-r文件中的内容自动读取<br>
     * <blockquote><pre>
     *        Map<Integer,String[]> items = FileUtil.ReadPartFile("output/part-r-00000");
     *         for(Integer key :items.keySet()){
     *             System.out.print(key+"=");
     *             String[] value= items.get(key);
     *             System.out.println(value[0]+","+value[1]);
     *         }</blockquote></pre>
     *
     * @param fileName MR的输出的文件
     * @return 输出格式为：Key-Value格式，Key是行号，value是当前行的数组
     * @throws IOException
     */
    public static Map<Integer, String[]> ReadPartFile(String fileName) throws IOException {

        return ReadPartFile(fileName, "utf-8");
    }
    /**
     * 将MR结果的输出文件夹中所有的part-r文件中的内容自动读取<br>
     * <blockquote><pre>
     *        Map<Integer,String[]> items = FileUtil.ReadPartFile("output/part-r-00000","utf-8");
     *         for(Integer key :items.keySet()){
     *             System.out.print(key+"=");
     *             String[] value= items.get(key);
     *             System.out.println(value[0]+","+value[1]);
     *         }</blockquote></pre>
     *
     * @param fileName MR的输出的文件
     * @param charset 当前文件的字符集编码（注意：MR的输入/出默认是UTF8编码）
     * @return 输出格式为：Key-Value格式，Key是行号，value是当前行的数组
     * @throws IOException
     */
    public static Map<Integer, String[]> ReadPartFile(String fileName,String charset) throws IOException {
        Map<Integer, String[]> items = new HashMap<>();
        File file = new File(fileName);//定义一个file对象，用来初始化FileReader
        if (!file.exists()) {

            throw new FileNotFoundException(fileName + "不存在！");
        }
        // 修正无法指定文件编码字符集的BUG
//        FileReader reader = null;//定义一个fileReader对象，用来初始化BufferedReader
        BufferedReader bReader = null;
        try {
//            reader = new FileReader(file);
            // 修正无法指定文件编码字符集的BUG
//            bReader = new BufferedReader(reader);//new一个BufferedReader对象，将文件内容读取到缓存
            bReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), charset));//new一个BufferedReader对象，将文件内容读取到缓存
            StringBuilder sb = new StringBuilder();//定义一个字符串缓存，将字符串存放缓存中
            String s = "";
            int index = 0;
            while ((s = bReader.readLine()) != null) {//逐行读取文件内容，不读取换行符和末尾的空格
                StringTokenizer st = new StringTokenizer(s, ", \t\n\r\f");
                String[] tmpList = new String[st.countTokens()];
                int i = 0;
                while (st.hasMoreTokens()) {
                    tmpList[i++] = st.nextToken();
                }

                items.put(index++, tmpList);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bReader.close();
        }

        return items;
    }
}
